package com.gopay.bis.cmbc.expay.operation;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.common.constants.bank.CmbcConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.cmbc.expay.CmbcExPayMessage;
import com.gopay.common.domain.bank.cmbc.expay.certification.CmbcAdPayCertificationQueryRes;
import com.gopay.common.domain.bank.cmbc.expay.certification.CmbcAdPayResCertification;
import com.gopay.common.domain.bank.cmbc.expay.crossbank.CmbcAdPayCBankQueryRes;
import com.gopay.common.domain.bank.cmbc.expay.crossbank.CmbcAdPayCBankResMessage;
import com.gopay.common.domain.bank.cmbc.expay.samebank.CmbcAdPayQueryResMessage;
import com.gopay.common.domain.bank.cmbc.expay.samebank.CmbcAdPayResMessage;
import com.gopay.common.domain.bank.cmbc.expay.whitelist.CmbcAdPayResWhiteList;
import com.gopay.common.exception.GopayException;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * 民生代扣返回对象解析类
 * 
 * @CmbcAdPayParseMessage.java
 * @author zhengxue
 * @2015-11-11 下午6:19:33 www.gopay.com.cn Inc.All rights reserved.
 */
public class CmbcAdPayParseMessage {
    private final static Logger logger = LoggerFactory.getLogger(CmbcAdPayParseMessage.class);
    private RSAHelper cipher;
    private String privateKey;
    private String publicKey;

    /**
     * 民生同行代扣交易返回结果对象解析
     * 
     * @param respMsg
     * @return
     * @throws GopayException
     */
    public CmbcExPayMessage parseSameAdPayResp(CmbcExPayMessage message, byte[] bytes) throws GopayException {
        logger.error("CmbcAdPayParseMessage parseSameAdPayResp start: ");
        try {
            int companyCodeLength = 15;// 合作方编码长度
            int messageCodeLength = 8;// 报文码长度
            int signCodeLength = 4;// 签名编码长度

            int headLength = companyCodeLength + messageCodeLength + signCodeLength;
            // 提取交易服务码
            String messageCode = new String(ArrayUtils.subarray(bytes, companyCodeLength, companyCodeLength
                    + messageCodeLength)).trim();
            String txnCode = messageCode.replaceAll(" ", ""); // 获取8位交易服务码
            message.setTxnCode(txnCode);
            // 提取签名长度
            int signlength = NumberUtils.toInt(new String(ArrayUtils.subarray(bytes, companyCodeLength
                    + messageCodeLength, headLength)).trim());
            logger.error("signlength:" + signlength);
            // 提取签名域
            byte[] signBytes = ArrayUtils.subarray(bytes, headLength, headLength + signlength);
            // 提取xml密文
            byte[] encryptedBytes = ArrayUtils.subarray(bytes, headLength + signlength, bytes.length);

            /*
             * byte[] xmlLen = new byte[8]; // 8位报文长度 System.arraycopy((byte[])
             * respMsg, 0, xmlLen, 0, 8); int leng = Integer.parseInt(new
             * String(xmlLen, "UTF-8").replaceFirst("^0*", "")); byte[]
             * signMessage = new byte[256]; // RSA签名域 byte[] cryptedBytes = new
             * byte[leng + 8 - 291]; // RSA密文
             * 
             * // 截掉8位报文长度+15位合作方编号+8位交易码+4位签名域长度，截取256位签名域
             * System.arraycopy((byte[]) respMsg, 35, signMessage, 0, 256); //
             * 截掉8位报文长度+15位合作方编号+8位交易码+4位签名域长度+256位签名域 System.arraycopy((byte[])
             * respMsg, 291, cryptedBytes, 0, leng + 8 - 291);
             */

            // 对密文解密
            byte[] xmlBytes = cipher.decryptRSA(privateKey, encryptedBytes, false, "UTF-8");
            String res = new String(xmlBytes, "UTF-8");
            message.setPlainMessage(res);
            logger.error("CmbcAdPayParseMessage parseSameAdPayResp " + txnCode + " resXML: " + res);
            // 验证签名
            boolean flag = cipher.verifyRSA(publicKey, xmlBytes, signBytes, false, "UTF-8");
            message.setFlag(flag);

            if (flag) {
                // 验签成功
                if (CmbcConstants.CMBCADPAY_PAYMENT.equals(txnCode)) {
                    // 同行代扣
                    CmbcAdPayResMessage resMsg = new CmbcAdPayResMessage();
                    // 解析
                    XStream xs = new XStream(new DomDriver());
                    xs.autodetectAnnotations(true);
                    xs.toXML(resMsg);
                    resMsg = (CmbcAdPayResMessage) xs.fromXML(res, resMsg);
                    message.setBankOrderId(resMsg.getTranId());
                    message.setRetType(resMsg.getRespType());
                    message.setRetCode(resMsg.getRespCode());
                    message.setRetMsg(resMsg.getRespMsg());
                } else if (CmbcConstants.CMBCADPAY_QUERY.equals(txnCode)) {
                    // 同行代扣交易查询
                    CmbcAdPayQueryResMessage resQueryMsg = new CmbcAdPayQueryResMessage();
                    // 解析
                    XStream xs = new XStream(new DomDriver());
                    xs.autodetectAnnotations(true);
                    xs.toXML(resQueryMsg);
                    resQueryMsg = (CmbcAdPayQueryResMessage) xs.fromXML(res, resQueryMsg);
                    message.setBankOrderId(resQueryMsg.getOriTranId());
                    message.setRetType(resQueryMsg.getRespType());
                    message.setRetCode(resQueryMsg.getRespCode());
                    message.setRetMsg(resQueryMsg.getRespMsg());
                    message.setOriAmt(resQueryMsg.getOriTranAmt());
                    message.setOriRetType(resQueryMsg.getOriRespType());
                    message.setOriRetCode(resQueryMsg.getOriRespCode());
                    message.setOriRetMsg(resQueryMsg.getOriRespMsg());
                } else {
                    // 错误业务码
                }
            }
            logger.error("CmbcAdPayParseMessage parseSameAdPayResp " + txnCode + " return: "
                    + ToStringBuilder.reflectionToString(message));
            return message;
        } catch (Exception e) {
            logger.error("CmbcAdPayParseMessage parseSameAdPayResp error: ", e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6057);
        }

    }
    
    /**
     * 民生跨行代扣交易返回结果对象解析
     * 
     * @param respMsg
     * @return
     * @throws GopayException
     */
    public CmbcExPayMessage parseCrossAdPayResp(CmbcExPayMessage message, byte[] bytes) throws GopayException {
        logger.error("CmbcAdPayParseMessage parseCrossAdPayResp start: ");
        try {
            int companyCodeLength = 8;// 合作方编码长度
            int messageCodeLength = 8;// 报文码长度
            int signCodeLength = 4;// 签名编码长度

            int headLength = companyCodeLength + messageCodeLength + signCodeLength;
            // 提取交易服务码
            String messageCode = new String(ArrayUtils.subarray(bytes, companyCodeLength, companyCodeLength
                    + messageCodeLength)).trim();
            String txnCode = messageCode.replaceAll(" ", ""); // 获取8位交易服务码
            message.setTxnCode(txnCode);
            // 提取签名长度
            int signlength = NumberUtils.toInt(new String(ArrayUtils.subarray(bytes, companyCodeLength
                    + messageCodeLength, headLength)).trim());
            logger.error("signlength:" + signlength);
            // 提取签名域
            byte[] signBytes = ArrayUtils.subarray(bytes, headLength, headLength + signlength);
            // 提取xml密文
            byte[] encryptedBytes = ArrayUtils.subarray(bytes, headLength + signlength, bytes.length);
            
            /*byte[] xmlLen = new byte[8]; // 8位报文长度
            System.arraycopy((byte[]) respMsg, 0, xmlLen, 0, 8);
            int leng = Integer.parseInt(new String(xmlLen, "UTF-8").replaceFirst("^0*", ""));
            byte[] signMessage = new byte[256]; // RSA签名域
            byte[] cryptedBytes = new byte[leng + 8 - 284]; // RSA密文

            // 截掉8位报文长度+8位合作方编号+8位交易码+4位签名域长度，截取256位签名域
            System.arraycopy((byte[]) respMsg, 28, signMessage, 0, 256);
            // 截掉8位报文长度+8位合作方编号+8位交易码+4位签名域长度+256位签名域
            System.arraycopy((byte[]) respMsg, 284, cryptedBytes, 0, leng + 8 - 284);*/

            // 对密文解密
            byte[] xmlBytes = cipher.decryptRSA(privateKey, encryptedBytes, false, "UTF-8");
            String res = new String(xmlBytes, "UTF-8");
            message.setPlainMessage(res);
            logger.error("CmbcAdPayParseMessage parseCrossAdPayResp " + txnCode + " resXML: " + res);
            // 验证签名
            boolean flag = cipher.verifyRSA(publicKey, xmlBytes, signBytes, false, "UTF-8");
            message.setFlag(flag);

            if (flag) {
                // 验签成功
                if (CmbcConstants.CMBCADPAY_CROSS_PAYMENT.equals(txnCode)) {
                    // 跨行代扣
                    CmbcAdPayCBankResMessage resMsg = new CmbcAdPayCBankResMessage();
                    // 解析
                    XStream xs = new XStream(new DomDriver());
                    xs.autodetectAnnotations(true);
                    xs.toXML(resMsg);
                    resMsg = (CmbcAdPayCBankResMessage) xs.fromXML(res, resMsg);
                    message.setBankOrderId(resMsg.getReqSerialNo());
                    message.setRetType(resMsg.getExecType());
                    message.setRetCode(resMsg.getExecCode());
                    message.setRetMsg(resMsg.getExecMsg());
                } else if (CmbcConstants.CMBCADPAY_CROSS_QUERY.equals(txnCode)) {
                    // 跨行代扣交易查询
                    CmbcAdPayCBankQueryRes resQueryMsg = new CmbcAdPayCBankQueryRes();
                    // 解析
                    XStream xs = new XStream(new DomDriver());
                    xs.autodetectAnnotations(true);
                    xs.toXML(resQueryMsg);
                    resQueryMsg = (CmbcAdPayCBankQueryRes) xs.fromXML(res, resQueryMsg);
                    message.setBankOrderId(resQueryMsg.getOriReqSerialNo());
                    message.setRetType(resQueryMsg.getExecType());
                    message.setRetCode(resQueryMsg.getExecCode());
                    message.setRetMsg(resQueryMsg.getExecMsg());
                    message.setOriRetType(resQueryMsg.getOriExecType());
                    message.setOriRetCode(resQueryMsg.getOriExecCode());
                    message.setOriRetMsg(resQueryMsg.getOriExecMsg());
                    // 跨行代扣返回无金额字段
//                    message.setOriAmt(TransUtil.amountConvert2Fen(message.getAmount().toString()));
                } else if (CmbcConstants.CMBCADPAY_CERTIFICATION.equals(txnCode)) {
                    // 实名身份认证
                    CmbcAdPayResCertification resMessage = new CmbcAdPayResCertification();
                    // 解析
                    XStream xs = new XStream(new DomDriver());
                    xs.autodetectAnnotations(true);
                    xs.toXML(resMessage);
                    resMessage = (CmbcAdPayResCertification) xs.fromXML(res, resMessage);
                    message.setBankOrderId(resMessage.getReqSerialNo());
                    message.setRetType(resMessage.getExecType());
                    message.setRetCode(resMessage.getExecCode());
                    message.setRetMsg(resMessage.getExecMsg());
                    message.setValidStatus(resMessage.getValidateStatus());
                    message.setReturnInfo(resMessage.getResv());
                } else if (CmbcConstants.CMBCADPAY_WHITELIST.equals(txnCode)) {
                    // 白名单采集
                    CmbcAdPayResWhiteList resWhite = new CmbcAdPayResWhiteList();
                    // 解析
                    XStream xs = new XStream(new DomDriver());
                    xs.autodetectAnnotations(true);
                    xs.toXML(resWhite);
                    resWhite = (CmbcAdPayResWhiteList) xs.fromXML(res, resWhite);
                    message.setBankOrderId(resWhite.getReqSerialNo());
                    message.setRetType(resWhite.getExecType());
                    message.setRetCode(resWhite.getExecCode());
                    message.setRetMsg(resWhite.getExecMsg());
                } else if (CmbcConstants.CMBCADPAY_CERTIFICATION_QUERY.equals(txnCode)) {
                    // 实名身份认证交易查询
                    CmbcAdPayCertificationQueryRes resQueryMessage = new CmbcAdPayCertificationQueryRes();
                    // 解析
                    XStream xs = new XStream(new DomDriver());
                    xs.autodetectAnnotations(true);
                    xs.toXML(resQueryMessage);
                    resQueryMessage = (CmbcAdPayCertificationQueryRes) xs.fromXML(res, resQueryMessage);
                    message.setBankOrderId(resQueryMessage.getOriReqSerialNo());
                    message.setRetType(resQueryMessage.getExecType());
                    message.setRetCode(resQueryMessage.getExecCode());
                    message.setRetMsg(resQueryMessage.getExecMsg());
                    message.setOriRetType(resQueryMessage.getOriExecType());
                    message.setOriRetCode(resQueryMessage.getOriExecCode());
                    message.setOriRetMsg(resQueryMessage.getOriExecMsg());
                    message.setValidStatus(resQueryMessage.getValidateStatus());
                } else {
                    // 错误业务码
                }
            }
            logger.error("CmbcAdPayParseMessage parseCrossAdPayResp " + txnCode + " return: "
                    + ToStringBuilder.reflectionToString(message));
            return message;
        } catch (Exception e) {
            logger.error("CmbcAdPayParseMessage parseCrossAdPayResp error: ", e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6057);
        }

    }

    public void setCipher(RSAHelper cipher) {
        this.cipher = cipher;
    }

    public void setPrivateKey(String privateKey) {
        this.privateKey = privateKey;
    }

    public void setPublicKey(String publicKey) {
        this.publicKey = publicKey;
    }

}
